﻿using System.Collections.Generic;
using System.Linq;
using System;
using System.ComponentModel.Composition;
using System.Collections.ObjectModel;

namespace TV_Organizer.TVRage
{
    [TVShowsConnector("TV Rage")]
    public class TVRageConnector : ITVShowsConnector<TVRageShow>
    {
        #region Singleton pattern
        private TVRageConnector()
        {
            this.Initialize();
        }

        private static TVRageConnector m_instance = new TVRageConnector();
        public static TVRageConnector Instance
        {
            get { return m_instance; }
        }
        #endregion

        #region props

        private ObservableCollection<TVRageShow> _shows = new ObservableCollection<TVRageShow>();
        public IEnumerable<TVRageShow> Shows { get { return _shows; } }

        #endregion

        private void Initialize()
        {

        }

        private IEnumerable<Episode> GetEpisodesForShow(TVRageShow show)
        {
            var l_result = new List<Episode>();

            var l_url = Constants.GetEpisodeListURL(show.TVRageID);
            var l_document = Helpers.WebHelpers.GetXmlFromUrl(l_url);

            foreach (var seasonNode in l_document.Descendants(Constants.SeasonNode))
            {
                int l_seasonNumber;
                var l_noAttr = seasonNode.Attribute(Constants.SeasonNodeNumberAttribute);
                if (l_noAttr == null || string.IsNullOrEmpty(l_noAttr.Value) || !int.TryParse(l_noAttr.Value, out l_seasonNumber))
                    continue;

                foreach (var episodeNode in seasonNode.Descendants(Constants.EpisodeNode))
                {
                    int l_episodeNumber;
                    var l_episodeNumberNode = episodeNode.Descendants(Constants.EpisodeNumberNode).FirstOrDefault();
                    var l_episodeTitleNode = episodeNode.Descendants(Constants.EpisodeTitleNode).FirstOrDefault();
                    if (l_episodeNumberNode == null || string.IsNullOrEmpty(l_episodeNumberNode.Value) || !int.TryParse(l_episodeNumberNode.Value, out l_episodeNumber)
                        || l_episodeTitleNode == null || string.IsNullOrEmpty(l_episodeTitleNode.Value))
                        continue;

                    l_result.Add(new Episode(l_seasonNumber, l_episodeNumber, l_episodeTitleNode.Value));
                }
            }

            return l_result;
        }

        public Episode GetEpisode(TVRageShow show, int seasonNumber, int episodeNumber)
        {
            lock (show.Episodes)
            {
                if(show.Episodes.Count == 0)
                    show.Episodes.AddRange(this.GetEpisodesForShow(show));
            }

            return show.Episodes.FirstOrDefault(ep => ep.Season == seasonNumber && ep.EpisodeNumber == episodeNumber);
        }

        public Showinfo GetShowInfo(TVRageShow show)
        {
            var l_url = Constants.GetShowInfoURL(show.TVRageID);
            var l_serializedShowInfo = Helpers.WebHelpers.GetStringFromUrl(l_url);

            return l_serializedShowInfo.DeserializeXML<Showinfo>();
        }

        public IEnumerable<TVRageShow> SearchShow(string search)
        {
            var serializedShowInfo = Helpers.WebHelpers.GetStringFromUrl(Constants.GetSearchShowURL(search));
            var result = serializedShowInfo.DeserializeXML<SearchResult>();
            if (result == null) return new List<TVRageShow>();

            return result.Shows.Select(s => s.ToTVRageShow()).ToList();
        }

        public Episode GetEpisode(TVShow show, int season, int episode)
        {
            throw new NotImplementedException();
        }
    }
}
